<template>
  <div class="home">
    <a-layout class="layout">
      <a-layout-sider
        v-model="collapsed"
        collapsible
        :trigger="null"
        breakpoint="lg"
        collapsedWidth="80"
        width="160"
      >
        <div class="logo">
          <span v-if="!collapsed">Z0SCAN</span>
          <a-icon 
            type="menu-unfold" 
            style="margin-left: 8px; cursor: pointer;"
            @click="toggleCollapse"
          />
        </div>
        <a-menu
          theme="dark"
          mode="inline"
          :defaultSelectedKeys="['0']"
          :selectedKeys="menuselect"
          @select="handleMenuSelect"
        >
          <a-menu-item key="0">
            <a-icon type="dashboard" />
            <span class="nav-text">概览</span>
          </a-menu-item>
          <a-menu-item key="1">
            <a-icon type="info-circle" />
            <span class="nav-text">详情</span>
          </a-menu-item>
          <a-menu-item key="2">
            <a-icon type="github" />
            <span class="nav-text">关于</span>
          </a-menu-item>
        </a-menu>
      </a-layout-sider>
      <a-layout>
        <a-layout-header class="header">
          <div class="header-right">
            <a-button type="primary" icon="reload" @click="refreshData" class="refresh-btn">刷新数据</a-button>
            <span class="datetime">DateTime: {{ formattedDateTime }}</span>
          </div>
        </a-layout-header>
        <a-layout-content class="content">
          <div class="page-content">
            <a-card v-if="menuselect[0] == '0'" class="card">
              <div class="chart-stats-container">
                <div ref="chart" class="chart-container"></div>
                <div class="stats-container">
                  <a-row :gutter="16">
                    <a-col :span="8" v-for="(stat, index) in stats" :key="index">
                      <a-card class="stat-card">
                        <div class="stat-value">{{ stat.value }}</div>
                        <div class="stat-title">{{ stat.title }}</div>
                        <div class="stat-icon" :style="{ backgroundColor: stat.color }">
                          <a-icon :type="stat.icon" />
                        </div>
                      </a-card>
                    </a-col>
                  </a-row>
                </div>
              </div>
            </a-card>
            
            <a-card v-else-if="menuselect[0] == '1'" class="card">
              <web-vulnerability
                :data="webData"
                :loading="loading"
              />
            </a-card>
            
            <a-card v-else-if="menuselect[0] == '2'" class="card">
              <h3 class="card-title">关于 Z0SCAN</h3>
              <a-divider />
              <a-descriptions bordered :column="1">
                <a-descriptions-item label="开发者">
                  <a-icon type="user" />
                  <span :style="{ marginLeft: '8px' }">JiuZero</span>
                </a-descriptions-item>
                <a-descriptions-item label="版本">
                  <a-icon type="info-circle" />
                  <span :style="{ marginLeft: '8px' }">^z0scan_version^</span>
                </a-descriptions-item>
                <a-descriptions-item label="GitHub仓库">
                  <a-icon type="github" />
                  <a 
                    href="https://github.com/jiuzero/z0scan" 
                    target="_blank"
                    :style="{ marginLeft: '8px' }"
                  >
                    https://github.com/jiuzero/z0scan
                  </a>
                </a-descriptions-item>
                <a-descriptions-item label="问题反馈">
                  <a-icon type="link" />
                  <a 
                    href="https://github.com/jiuzero/z0scan/issues" 
                    target="_blank"
                    :style="{ marginLeft: '8px' }"
                  >
                    https://github.com/jiuzero/z0scan/issues
                  </a>
                </a-descriptions-item>
              </a-descriptions>
            </a-card>
          </div>
        </a-layout-content>

        <!-- 页脚 -->
        <a-layout-footer class="footer">
          Z0SCAN Security Scan Report ©2025 Powered by JiuZero
        </a-layout-footer>
      </a-layout>
    </a-layout>
  </div>
</template>

<script>
import WebVulnerability from "../components/WebVulnerability";
import * as echarts from 'echarts';

export default {
  name: "Home",
  components: {
    WebVulnerability,
  },
  created() {
    if (document.readyState === 'complete') {
      this.loadVulns(0)
    } else {
      window.addEventListener("load", () => {
        this.loadVulns(0)
      });
    }
  },
  mounted() {
    if (!window.fetch) {
      this.$message.error("Please use modern browser like Chrome, Firefox, Safari to open the report.")
    }
    this.initStats();
  },
  data() {
    return {
      collapsed: false,
      loading: true,
      webData: [],
      modalVisible: false,
      menuselect: ['0'],
      currentDateTime: new Date(),
      chart: null,
      stats: [
        { title: '总漏洞数', value: 0, icon: 'ios-bug', color: '#ed4014' },
        // { title: '高危漏洞', value: 0, icon: 'ios-alert', color: '#f5222d' },
        // { title: '中危漏洞', value: 0, icon: 'ios-warning', color: '#fa8c16' },
        // { title: '低危漏洞', value: 0, icon: 'ios-information', color: '#1890ff' },
      ]
    };
  },
  watch: {
    menuselect(newVal) {
      if (newVal[0] === '0') {
        this.$nextTick(() => {
          this.initChart();
        });
      }
    },
    webData: {
      handler(newVal) {
        this.updateStats(newVal);
      },
      immediate: true,
      deep: true
    }
  },
  computed: {
    formattedDateTime() {
      return this.currentDateTime.toLocaleString();
    }
  },
  methods: {
    handleMenuSelect({ key }) {
      this.menuselect = [key];
    },
    toggleCollapse() {
      this.collapsed = !this.collapsed;
    },
    refreshData() {
      this.loading = true;
      this.loadVulns();
      this.currentDateTime = new Date();
      this.$message.success('数据已刷新');
    },
    loadVulns() {
      for (let data of [window.webVulns]) {
        for (let [i, obj] of data.entries()) {
          obj.id = i
        }
      }
      this.webData = window.webVulns;
      this.loading = false;
      this.initChart();
    },
    initStats() {
      const now = new Date();
      const dateStr = now.toLocaleDateString();
      const timeStr = now.toLocaleTimeString();
      
      this.stats[4].value = [...new Set(this.webData.map(item => item.url))].length || 0;
      this.stats[5].value = `${dateStr} ${timeStr}`;
    },
    updateStats(data) {
      if (!data || !data.length) return;
      
      // 统计各漏洞类型的数量
      const vulCount = {};
      data.forEach(item => {
        vulCount[item.vultype] = (vulCount[item.vultype] || 0) + 1;
      });
      
      // 更新统计卡片
      this.stats[0].value = data.length;
      this.stats[1].value = Object.values(vulCount).reduce((acc, val) => {
        const type = data.find(item => item.vultype === Object.keys(vulCount)[acc.count])?.vultype;
        return acc.count + (this.isHighRisk(type) ? val : 0);
      }, { count: 0 }).count;
      
      // 这里简化了中危和低危的统计，实际应根据漏洞类型分类
      this.stats[2].value = Math.floor(data.length * 0.3);
      this.stats[3].value = Math.floor(data.length * 0.2);
    },
    isHighRisk(type) {
      const highRiskTypes = ['SQLI', 'CMD_INNJECTION', 'CODE_INJECTION', 'FILEUPLOAD'];
      return highRiskTypes.includes(type);
    },
    initChart() {
      if (this.chart) {
        this.chart.dispose();
      }
      
      const vulCount = {};
      this.webData.forEach(item => {
        vulCount[item.vultype] = (vulCount[item.vultype] || 0) + 1;
      });

      const chartData = Object.keys(vulCount).map(key => {
        return {
          name: key,
          value: vulCount[key],
          itemStyle: {
            color: this.vulType2Tag(key)
          }
        };
      });

      this.chart = echarts.init(this.$refs.chart);
      const option = {
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b}: {c} ({d}%)'
        },
        legend: {
          orient: 'vertical',
          right: 10,
          top: 'center',
          data: Object.keys(vulCount)
        },
        series: [
          {
            name: '漏洞类型分布',
            type: 'pie',
            radius: ['40%', '70%'],
            center: ['35%', '50%'], // 调整饼图位置
            avoidLabelOverlap: false,
            itemStyle: {
              borderRadius: 10,
              borderColor: '#fff',
              borderWidth: 2
            },
            label: {
              show: false,
              position: 'center'
            },
            emphasis: {
              label: {
                show: true,
                fontSize: '18',
                fontWeight: 'bold'
              }
            },
            labelLine: {
              show: false
            },
            data: chartData
          }
        ]
      };
      this.chart.setOption(option);
      
      window.addEventListener('resize', () => {
        this.chart && this.chart.resize();
      });
    },
    vulType2Tag(vultype) {
      const VULREPLACE = {
        CMD_INNJECTION: "#f50",
        CODE_INJECTION: "#f50",
        XSS: "#faad14",
        SQLI: "#f50",
        FILEUPLOAD: "#f50",
        UNAUTH: "#faad14",
        CORS: "#1890ff",
        PATH_TRAVERSAL: "#1890ff",
        XXE: "#f50",
        WEAK_PASSWORD: "#1890ff",
        SSRF: "#52c41a",
        REDIRECT: "#52c41a",
        CRLF: "#faad14",
        SENSITIVE: "#1890ff",
        OTHER: "#52c41a"
      };
      return VULREPLACE[vultype] || '#d9d9d9';
    }
  },
  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose();
    }
  }
};
</script>

<style lang="less" scoped>
.home {
  height: 100vh;
  overflow: hidden;
  
  .layout {
    height: 100%;
  }
  
  .logo {
    height: 64px;
    line-height: 64px;
    padding-left: 20px;
    color: #fff;
    font-size: 20px;
    font-weight: bold;
    overflow: hidden;
  }
  
  .header {
    background: #fff;
    padding: 0 20px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
    
    .trigger {
      font-size: 18px;
      padding: 0 12px;
      cursor: pointer;
      transition: color 0.3s;
      
      &:hover {
        color: #1890ff;
      }
    }
    
    .header-right {
      display: flex;
      align-items: center;
      
      .datetime {
        margin-left: 16px;
        color: rgba(0, 0, 0, 0.65);
      }
    }
  }
  
  .content {
    margin: 16px;
    background: #f0f2f5;
    
    .page-content {
      padding: 16px;
      background: #fff;
      min-height: calc(100% - 64px);
    }
    
    .card {
      margin-bottom: 16px;
      border-radius: 4px;
      
      &-title {
        margin-bottom: 16px;
        color: rgba(0, 0, 0, 0.85);
        font-weight: 500;
      }
    }
    
    .chart-stats-container {
      display: flex;
      gap: 24px;
      align-items: flex-start;
    }
    
    .chart-container {
      width: 40%;
      height: 400px;
    }
    
    .stats-container {
      width: 60%;
      margin-top: 0;
      
      .stat-card {
        text-align: center;
        position: relative;
        overflow: hidden;
        
        .stat-value {
          font-size: 24px;
          font-weight: bold;
          color: rgba(0, 0, 0, 0.85);
          margin-bottom: 8px;
        }
        
        .stat-title {
          color: rgba(0, 0, 0, 0.45);
          font-size: 14px;
        }
        
        .stat-icon {
          position: absolute;
          top: -10px;
          right: -10px;
          width: 60px;
          height: 60px;
          border-radius: 50%;
          opacity: 0.1;
          display: flex;
          align-items: center;
          justify-content: center;
          font-size: 24px;
          color: #fff;
        }
      }
    }
  }
  
  .footer {
    text-align: center;
    color: rgba(0, 0, 0, 0.45);
    font-size: 14px;
    background: #f0f2f5;
    border-top: 1px solid #e8eaec;
  }
  
  .about-content {
    p {
      margin-bottom: 12px;
      
      a {
        margin-left: 8px;
      }
    }
  }
}
</style>